function constrainLayout(cache, dataList) {
    let children = filterChildren(cache, dataList);
    let childDatas = preConstainLayout(cache, children);

    for (let i = 0; i < childDatas.length; i++) {
        let data = childDatas[i];
        setupLevel(cache.data, data);
    }
    return cache;
}

function preConstainLayout(cache, childDatas) {
    for (let i = 0; i < childDatas.length; i++) {
        let a = childDatas[i];
        let aCache = getCache(a);
        let parent = findParent(aCache, childDatas);
        if (parent && cache != parent) {
            setupLevel(parent, a);
        }
    } 

    childDatas = childDatas.filter(function (item) {
        let cache = getCache(item);
        let type = figure(item);
        let hasChildren = (cache.children && cache.children.length > 0) || false;
        let isGroup = type == "SizedBox" && hasChildren;
        return (!cache.parent && type != "SizedBox") || isGroup;
    });

    genConsRelative(childDatas);
    return childDatas;
}

function genConsRelative(childDatas) {
    for (let i = 0; i < childDatas.length; i++) {
        let a = childDatas[i];
        let aCache = getCache(a);
        newConstraintRelative(aCache);

        for (let j = i + 1; j < childDatas.length; j++) {
            let b = childDatas[j];
            let bCache = getCache(b);
            newConstraintRelative(bCache);

            if (isIntersect(a, b)) {
                if (aCache.index < bCache.index) {
                    bCache.relative.isFloat = true;
                } else {
                    aCache.relative.isFloat = true;
                }
            } else {
                // 非重叠情况下判断ab的相对位置
                if (isYIntersect(a, b)) {
                    if (a.x + a.width < b.x) {
                        aCache.relative.right.push(bCache);
                        bCache.relative.left.push(aCache);
                    } else {
                        aCache.relative.left.push(bCache);
                        bCache.relative.right.push(aCache);
                    }
                } else if (isXIntersect(a, b)) {
                    if (a.y + a.height < b.y) {
                        aCache.relative.bottom.push(bCache);
                        bCache.relative.top.push(aCache);
                    } else {
                        aCache.relative.top.push(bCache);
                        bCache.relative.bottom.push(aCache);
                    }
                } else {
                    console.log("完全不关联", a.id, b.id);
                }
            }
        }
    }

    for (let i = 0; i < childDatas.length; i++) {
        let data = childDatas[i];
        let cache = getCache(data);
        cache.relative.left = cache.relative.left.filter(function (item) {
            return !item.relative.isFloat;
        });
        if (cache.relative.left.length > 0) {
            cache.relative.left.sort(function (a, b) {
                return b.x - a.x;
            });

            cache.relative.leftBro = [];

            for (let j = 0; j < cache.relative.left.length; j++) {
                let item = cache.relative.left[j].data;
                let valid = true;
                for (let k = 0; k < cache.relative.leftBro.length; k++) {
                    let bro = cache.relative.leftBro[k];
                    // x、y轴重合且更贴近
                    if ((item.x > bro.data.x + bro.data.width) && isYIntersect(item, bro.data)) {
                        bro.valid = false;
                    } else if (!isYIntersect(item, bro.data)) {
                        continue;
                    } else {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    cache.relative.leftBro = cache.relative.leftBro.filter(function (item) {
                        return item.valid;
                    })
                    cache.relative.leftBro.push({
                        data: item,
                        valid: true
                    });
                }
            }
        }

        cache.relative.right = cache.relative.right.filter(function (item) {
            return !item.relative.isFloat;
        });
        if (cache.relative.right.length > 0) {
            cache.relative.right.sort(function (a, b) {
                return a.x - b.x;
            });

            cache.relative.rightBro = [];

            for (let j = 0; j < cache.relative.right.length; j++) {
                let item = cache.relative.right[j].data;
                let valid = true;
                for (let k = 0; k < cache.relative.rightBro.length; k++) {
                    let bro = cache.relative.rightBro[k];
                    // x、y轴重合且更贴近
                    if ((item.x + item.width < bro.data.x) && isYIntersect(item, bro.data)) {
                        bro.valid = false;
                    } else if (!isYIntersect(item, bro.data)) {
                        continue;
                    } else {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    cache.relative.rightBro = cache.relative.rightBro.filter(function (item) {
                        return item.valid;
                    })
                    cache.relative.rightBro.push({
                        data: item,
                        valid: true
                    });
                }
            }
        }


        cache.relative.top = cache.relative.top.filter(function (item) {
            return !item.relative.isFloat;
        });
        if (cache.relative.top.length > 0) {
            cache.relative.top.sort(function (a, b) {
                return b.y - a.y;
            });

            cache.relative.topBro = [];

            for (let j = 0; j < cache.relative.top.length; j++) {
                let item = cache.relative.top[j].data;
                let valid = true;
                for (let k = 0; k < cache.relative.topBro.length; k++) {
                    let bro = cache.relative.topBro[k];
                    // x、y轴重合且更贴近
                    if ((item.y > bro.data.y + bro.data.height) && isXIntersect(item, bro.data)) {
                        bro.valid = false;
                    } else if (!isXIntersect(item, bro.data)) {
                        continue;
                    } else {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    cache.relative.topBro = cache.relative.topBro.filter(function (item) {
                        return item.valid;
                    })
                    cache.relative.topBro.push({
                        data: item,
                        valid: true
                    });
                }
            }
        }

        cache.relative.bottom = cache.relative.bottom.filter(function (item) {
            return !item.relative.isFloat;
        });
        if (cache.relative.bottom.length > 0) {
            cache.relative.bottom.sort(function (a, b) {
                return a.y - b.y;
            });

            cache.relative.bottomBro = [];

            for (let j = 0; j < cache.relative.bottom.length; j++) {
                let item = cache.relative.bottom[j].data;
                let valid = true;
                for (let k = 0; k < cache.relative.bottomBro.length; k++) {
                    let bro = cache.relative.bottomBro[k];
                    // x、y轴重合且更贴近
                    if ((item.y + item.height < bro.data.y) && isXIntersect(item, bro.data)) {
                        bro.valid = false;
                    } else if (!isXIntersect(item, bro.data)) {
                        continue;
                    } else {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    cache.relative.bottomBro = cache.relative.bottomBro.filter(function (item) {
                        return item.valid;
                    })
                    cache.relative.bottomBro.push({
                        data: item,
                        valid: true
                    });
                }
            }
        }
    }
}

function newConstraintRelative(cache) {
    cache.relative = cache.relative || {
        left: [],
        right: [],
        top: [],
        bottom: [],
        isFloat: false
    };
}